package com.example.acceletracks;

import java.util.List;
import java.util.Vector;

import com.google.android.gms.maps.model.LatLng;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;

public class AcceleSensor implements SensorEventListener {

	private SensorManager sManager;
	private final MapActivity mContext;
	
	private AcceleRoute acceleRoute=null;
	private AcceleHoles acceleHoles=null;
	private GPSTracker gps;
	
	private long startTime;
	private long lastUpdateTime;
	
	private List<Double> samples;
	
	private double currVector;
	private double currMean;
	private LatLng currLatLng;

	protected static final String DEFAULT_SAMPLES_AMOUNT = "20"; // //10*160 =1600 ms
	protected static final String DEFAULT_DELTA_ACC = "2";
	private int samplesAmount;
	private float deltaAcc;
	
	//private final double deltaT=0.160; //16ms
	//private double currSpeed=0;
	//private double prevSpeed;
	

	public AcceleSensor(MapActivity mContext) {

		this.mContext = mContext;
		this.gps=mContext.getGPS();
		
		sManager = (SensorManager) (this.mContext.getSystemService(MapActivity.SENSOR_SERVICE));

		setStartTime(System.currentTimeMillis());
		lastUpdateTime=startTime;
		
		samples=new Vector<Double>();
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {

	}

	@Override
	public void onSensorChanged(SensorEvent event) {
		if(gps.getRoute()!=null)
		{
			if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION && gps.getRoute().getLength()>0)
			{
				currVector = calculateVector(event);
				currMean = calculateMean();
				currLatLng = gps.getRoute().getEndPoint();
				
				update();
				addValues(event);

				//prevSpeed = currSpeed;
				//currSpeed=gps.getRoute().getEndSpeedPoint(); 
			}
		}

	}
	
	private void update() {
			
		if(samples.size()>samplesAmount)
		{
			if(currVector>(currMean+deltaAcc))
			{
				acceleHoles.addPoint(currLatLng);
				mContext.updateAcc(currLatLng);
				Log.d("Proximity","addPoint()");
			}
		}	
	}

	private double calculateVector(SensorEvent event) {
		
		float[] values = event.values;
		
		return Math.sqrt(values[0]*values[0] + values[1]*values[1]);
	}

	private double calculateMean() {
		
		if(samples.size()>samplesAmount)
			samples.remove(0);
		
		samples.add(currVector);
		
		double mean=0.0;
		
		for(Double v: samples)
			mean+=v;
		mean/=samples.size();
		
		return mean;			
	}

	private void addValues(SensorEvent event)
	{
		float[] values = event.values;
		long actualTimeClock = System.currentTimeMillis();
		float time_diff=actualTimeClock-lastUpdateTime;
		float speed=gps.getRoute().getEndSpeedPoint();
		LatLng point=gps.getRoute().getEndPoint();
		
		
		Node node = new Node(values, (actualTimeClock-startTime)/1000, time_diff, speed, point);
		if(acceleRoute!=null)
		acceleRoute.addNode(node);
		
		lastUpdateTime=actualTimeClock;
	}
	
	public void stopUsingAccele()
	{
		Log.d("location", "stopUsingAccele()");
		sManager.unregisterListener(this);
	}
	
	public void startUsingAccele()
	{
		Log.d("location", "startUsingAccele()");
		sManager.registerListener(this, sManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION), SensorManager.SENSOR_DELAY_NORMAL);
	}

	public void setAcceleRoute(AcceleRoute acceleRoute) {
		
		this.acceleRoute=acceleRoute;
		
	}

	public AcceleRoute getAcceleRoute() {
		
		return acceleRoute;
	}
	
	public void setAcceleHoles(AcceleHoles acceleHoles) {
		this.acceleHoles = acceleHoles;
	}
	
	public AcceleHoles getAcceleHoles() {
		return acceleHoles;
	}

	public long getStartTime() {
		return startTime;
	}

	public void setStartTime(long startTime) {
		this.startTime = startTime;
	}

	public void setSamplesAmount(int samplesAmount) {
		this.samplesAmount = samplesAmount;
	}

	public void setDeltaAcc(float deltaAcc) {
		this.deltaAcc = deltaAcc;
	}
	
	/*private double calculateVector(SensorEvent event) {
		
		float[] values = event.values;
		
		return Math.sqrt(values[0]*values[0] + values[1]*values[1] + values[2]*values[2]);
	}
		
	private double calculateVector2(SensorEvent event) {
		
		double v=calculateVector(event);
		double dSpeed=Math.abs(prevSpeed-currSpeed);
		double acc=dSpeed/deltaT;
		v-=acc;
		
		if(v>0)
			return v;
		else
			return 0;
	}*/
	
}
